package org.example.httpclient;

import okhttp3.*;
import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.Security;
import java.time.Instant;
import java.util.*;

public class RealNameAuth {
    private static final Logger logger = LoggerFactory.getLogger(RealNameAuth.class);
    private static final String AES_ALGORITHM = "AES/ECB/PKCS5Padding";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    private String accountId;
    private String token;
    private String phone;
    private String name;
    private String identifyCardNO;
    private String photo;
    private String callbackUrl;
    private long timestamp;
    private String sig;
    private String baseUrl;

    public RealNameAuth(String accountId, String token, String phone, String name, String identifyCardNO, String photo, String callbackUrl) throws Exception {
        this.accountId = accountId;
        this.token = token;
        this.phone = phone;
        this.name = name;
        this.identifyCardNO = identifyCardNO;
        this.photo = photo;
        this.callbackUrl = callbackUrl;
        this.timestamp = Instant.now().toEpochMilli();
        this.sig = md5(accountId + token + timestamp);
//        this.baseUrl = String.format("https://101.37.133.245:11008/voice/1.0.0/realNameAuth/%s/%s", accountId, sig);
        this.baseUrl = String.format("http://127.0.0.1:8889/voicerxd_war/1.0.0/realNameAuth/%s/%s", accountId, sig);
    }

    private String getAuthorization() {
        String authString = String.format("%s:%d", accountId, timestamp);
        return Base64.encodeBase64String(authString.getBytes(StandardCharsets.UTF_8));
    }

    private String encrypt(String plaintext) {
        try {
            // 确保密钥长度为16字节（128位）
            String key = token.substring(0, Math.min(token.length(), 16));
            if (key.length() != 16) {
                throw new IllegalArgumentException("Key must be 16 bytes long for AES-128");
            }

            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
            SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);

//            byte[] paddedPlaintext = pad(plaintext.getBytes(StandardCharsets.UTF_8), 128);
            byte[] paddedPlaintext = plaintext.getBytes(StandardCharsets.UTF_8);
            byte[] ciphertext = cipher.doFinal(paddedPlaintext);

            return Base64.encodeBase64String(ciphertext);
        } catch (Exception e) {
            logger.error("Error in encrypt method: {}", e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    private byte[] pad(byte[] data, int blockSize) {
        int paddingLength = blockSize - (data.length % blockSize);
        byte[] paddedData = Arrays.copyOf(data, data.length + paddingLength);
        Arrays.fill(paddedData, data.length, paddedData.length, (byte) paddingLength);
        return paddedData;
    }

    private String sendRequest() {
        try {
            Map<String, String> headers = new HashMap<>();
            headers.put("Authorization", getAuthorization());
            headers.put("Content-Type", "application/json");

            Map<String, Object> body = new HashMap<>();
            body.put("phoneNo", encrypt(phone));
            body.put("name", encrypt(name));
            body.put("identifyCardNO", encrypt(identifyCardNO));
            body.put("photo", encrypt(photo));
            body.put("callbackUrl", callbackUrl);

            OkHttpClient client = new OkHttpClient.Builder()
                    .hostnameVerifier((hostname, session) -> true)
                    .build();

            RequestBody requestBody = RequestBody.create(
                    new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsBytes(body),
                    okhttp3.MediaType.get("application/json; charset=utf-8")
            );

            Request request = new Request.Builder()
                    .url(baseUrl)
                    .post(requestBody)
                    .headers(Headers.of(headers))
                    .build();

            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                logger.info("Request successful: {}, {}, {}", phone, name, response.body().string());
                return response.body().string();
            } else {
                logger.error("Request failed: {}", response.body().string());
                throw new RuntimeException("Request failed with code: " + response.code());
            }
        } catch (Exception e) {
            logger.error("Error in send_request method: {}", e.getMessage(), e);
            throw new RuntimeException(e);
        }
    }

    private String md5(String input) throws Exception {
        MessageDigest md = MessageDigest.getInstance("MD5");
        byte[] digest = md.digest(input.getBytes(StandardCharsets.UTF_8));
        return DatatypeConverter.printHexBinary(digest).toLowerCase();
    }
    private static String readImageAsBase64(String imagePath) throws Exception {
        byte[] imageBytes = Files.readAllBytes(Paths.get(imagePath));
        return Base64.encodeBase64String(imageBytes);
    }
    public static void main(String[] args) throws Exception {
        String accountId = "116471";
//        String accountId = "520576";
        String token = "0aa318c7eb954621a37755a1170344f4";
//        String token = "432f3424e6b94d209b07161eb9405f6c";
        String photo = readImageAsBase64("src/main/resources/13211000006.jpg");

        RealNameAuth realNameAuth = new RealNameAuth(accountId, token, "15261426686", "赵康", "320121199509170030", photo, "http://1.207.120.35:12655/receive");
        String result = realNameAuth.sendRequest();
        System.out.println(result);
    }
}
